home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-ALPH.{_4 / SPINLOCK.H < prev    next >
C/C++ Source or Header  |  1999-09-17  |  7KB  |  252 lines

  1. #ifndef _ALPHA_SPINLOCK_H
  2. #define _ALPHA_SPINLOCK_H
  3.  
  4. #include <asm/system.h>
  5.  
  6. #ifndef __SMP__
  7.  
  8. /*
  9.  * Your basic spinlocks, allowing only a single CPU anywhere
  10.  *
  11.  * Gcc-2.7.x has a nasty bug with empty initializers.
  12.  */
  13. #if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)
  14.   typedef struct { } spinlock_t;
  15.   #define SPIN_LOCK_UNLOCKED (spinlock_t) { }
  16. #else
  17.   typedef struct { int gcc_is_buggy; } spinlock_t;
  18.   #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
  19. #endif
  20.  
  21. #define spin_lock_init(lock)            ((void) 0)
  22. #define spin_lock(lock)                ((void) 0)
  23. #define spin_trylock(lock)            ((void) 0)
  24. #define spin_unlock_wait(lock)            ((void) 0)
  25. #define spin_unlock(lock)            ((void) 0)
  26. #define spin_lock_irq(lock)            cli()
  27. #define spin_unlock_irq(lock)            sti()
  28.  
  29. #define spin_lock_irqsave(lock, flags)        save_and_cli(flags)
  30. #define spin_unlock_irqrestore(lock, flags)    restore_flags(flags)
  31.  
  32. /*
  33.  * Read-write spinlocks, allowing multiple readers
  34.  * but only one writer.
  35.  *
  36.  * NOTE! it is quite common to have readers in interrupts
  37.  * but no interrupt writers. For those circumstances we
  38.  * can "mix" irq-safe locks - any writer needs to get a
  39.  * irq-safe write-lock, but readers can get non-irqsafe
  40.  * read-locks.
  41.  *
  42.  * Gcc-2.7.x has a nasty bug with empty initializers.
  43.  */
  44. #if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)
  45.   typedef struct { } rwlock_t;
  46.   #define RW_LOCK_UNLOCKED (rwlock_t) { }
  47. #else
  48.   typedef struct { int gcc_is_buggy; } rwlock_t;
  49.   #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
  50. #endif
  51.  
  52. #define read_lock(lock)                ((void) 0)
  53. #define read_unlock(lock)            ((void) 0)
  54. #define write_lock(lock)            ((void) 0)
  55. #define write_unlock(lock)            ((void) 0)
  56. #define read_lock_irq(lock)            cli()
  57. #define read_unlock_irq(lock)            sti()
  58. #define write_lock_irq(lock)            cli()
  59. #define write_unlock_irq(lock)            sti()
  60.  
  61. #define read_lock_irqsave(lock, flags)        save_and_cli(flags)
  62. #define read_unlock_irqrestore(lock, flags)    restore_flags(flags)
  63. #define write_lock_irqsave(lock, flags)        save_and_cli(flags)
  64. #define write_unlock_irqrestore(lock, flags)    restore_flags(flags)
  65.  
  66. #else /* __SMP__ */
  67.  
  68. #include <linux/kernel.h>
  69. #include <asm/current.h>
  70.  
  71. #define DEBUG_SPINLOCK 1
  72. #define DEBUG_RWLOCK 1
  73.  
  74. /*
  75.  * Simple spin lock operations.  There are two variants, one clears IRQ's
  76.  * on the local processor, one does not.
  77.  *
  78.  * We make no fairness assumptions. They have a cost.
  79.  */
  80.  
  81. typedef struct {
  82.     volatile unsigned int lock;
  83. #if DEBUG_SPINLOCK
  84.     char debug_state, target_ipl, saved_ipl, on_cpu;
  85.     void *previous;
  86.     struct task_struct * task;
  87. #endif
  88. } spinlock_t;
  89.  
  90. #if DEBUG_SPINLOCK
  91. #define SPIN_LOCK_UNLOCKED (spinlock_t) {0, 1, 0, 0, 0, 0}
  92. #define spin_lock_init(x)                        \
  93.     ((x)->lock = 0, (x)->target_ipl = 0, (x)->debug_state = 1,    \
  94.      (x)->previous = 0, (x)->task = 0)
  95. #else
  96. #define SPIN_LOCK_UNLOCKED    (spinlock_t) { 0 }
  97. #define spin_lock_init(x)    ((x)->lock = 0)
  98. #endif
  99.  
  100. #define spin_unlock_wait(x) \
  101.     ({ do { barrier(); } while(((volatile spinlock_t *)x)->lock); })
  102.  
  103. typedef struct { unsigned long a[100]; } __dummy_lock_t;
  104. #define __dummy_lock(lock) (*(__dummy_lock_t *)(lock))
  105.  
  106. #if DEBUG_SPINLOCK
  107. extern void spin_unlock(spinlock_t * lock);
  108. extern void spin_lock(spinlock_t * lock);
  109. extern int spin_trylock(spinlock_t * lock);
  110.  
  111. #define spin_lock_own(LOCK, LOCATION)                    \
  112. do {                                    \
  113.     if (!((LOCK)->lock && (LOCK)->on_cpu == smp_processor_id()))    \
  114.         printk("%s: called on %d from %p but lock %s on %d\n",    \
  115.                LOCATION, smp_processor_id(),            \
  116.                __builtin_return_address(0),            \
  117.                (LOCK)->lock ? "taken" : "freed", (LOCK)->on_cpu); \
  118. } while (0)
  119. #else
  120. static inline void spin_unlock(spinlock_t * lock)
  121. {
  122.     mb();
  123.     lock->lock = 0;
  124. }
  125.  
  126. static inline void spin_lock(spinlock_t * lock)
  127. {
  128.     long tmp;
  129.  
  130.     /* Use sub-sections to put the actual loop at the end
  131.        of this object file's text section so as to perfect
  132.        branch prediction.  */
  133.     __asm__ __volatile__(
  134.     "1:    ldl_l    %0,%1\n"
  135.     "    blbs    %0,2f\n"
  136.     "    or    %0,1,%0\n"
  137.     "    stl_c    %0,%1\n"
  138.     "    beq    %0,2f\n"
  139.     "    mb\n"
  140.     ".section .text2,\"ax\"\n"
  141.     "2:    ldl    %0,%1\n"
  142.     "    blbs    %0,2b\n"
  143.     "    br    1b\n"
  144.     ".previous"
  145.     : "=r" (tmp), "=m" (__dummy_lock(lock))
  146.     : "m"(__dummy_lock(lock)));
  147. }
  148.  
  149. #define spin_trylock(lock) (!test_and_set_bit(0,(lock)))
  150. #define spin_lock_own(LOCK, LOCATION)    ((void)0)
  151. #endif /* DEBUG_SPINLOCK */
  152.  
  153. #define spin_lock_irq(lock) \
  154.   (__cli(), spin_lock(lock))
  155. #define spin_unlock_irq(lock) \
  156.   (spin_unlock(lock), __sti())
  157. #define spin_lock_irqsave(lock, flags) \
  158.   (__save_and_cli(flags), spin_lock(lock))
  159. #define spin_unlock_irqrestore(lock, flags) \
  160.   (spin_unlock(lock), __restore_flags(flags))
  161.  
  162. /***********************************************************/
  163.  
  164. typedef struct { volatile int write_lock:1, read_counter:31; } rwlock_t;
  165.  
  166. #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
  167.  
  168. #if DEBUG_RWLOCK
  169. extern void write_lock(rwlock_t * lock);
  170. extern void read_lock(rwlock_t * lock);
  171. #else
  172. static inline void write_lock(rwlock_t * lock)
  173. {
  174.     long regx;
  175.  
  176.     __asm__ __volatile__(
  177.     "1:    ldl_l    %1,%0\n"
  178.     "    bne    %1,6f\n"
  179.     "    or    $31,1,%1\n"
  180.     "    stl_c    %1,%0\n"
  181.     "    beq    %1,6f\n"
  182.     "    mb\n"
  183.     ".section .text2,\"ax\"\n"
  184.     "6:    ldl    %1,%0\n"
  185.     "    bne    %1,6b\n"
  186.     "    br    1b\n"
  187.     ".previous"
  188.     : "=m" (__dummy_lock(lock)), "=&r" (regx)
  189.     : "0" (__dummy_lock(lock))
  190.     );
  191. }
  192.  
  193. static inline void read_lock(rwlock_t * lock)
  194. {
  195.     long regx;
  196.  
  197.     __asm__ __volatile__(
  198.     "1:    ldl_l    %1,%0\n"
  199.     "    blbs    %1,6f\n"
  200.     "    subl    %1,2,%1\n"
  201.     "    stl_c    %1,%0\n"
  202.     "    beq    %1,6f\n"
  203.     "4:    mb\n"
  204.     ".section .text2,\"ax\"\n"
  205.     "6:    ldl    %1,%0\n"
  206.     "    blbs    %1,6b\n"
  207.     "    br    1b\n"
  208.     ".previous"
  209.     : "=m" (__dummy_lock(lock)), "=&r" (regx)
  210.     : "m" (__dummy_lock(lock))
  211.     );
  212. }
  213. #endif /* DEBUG_RWLOCK */
  214.  
  215. static inline void write_unlock(rwlock_t * lock)
  216. {
  217.     mb();
  218.     *(volatile int *)lock = 0;
  219. }
  220.  
  221. static inline void read_unlock(rwlock_t * lock)
  222. {
  223.     long regx;
  224.     __asm__ __volatile__(
  225.     "1:    ldl_l    %1,%0\n"
  226.     "    addl    %1,2,%1\n"
  227.     "    stl_c    %1,%0\n"
  228.     "    beq    %1,6f\n"
  229.     ".section .text2,\"ax\"\n"
  230.     "6:    br    1b\n"
  231.     ".previous"
  232.     : "=m" (__dummy_lock(lock)), "=&r" (regx)
  233.     : "m" (__dummy_lock(lock)));
  234. }
  235.  
  236. #define read_lock_irq(lock)    (__cli(), read_lock(lock))
  237. #define read_unlock_irq(lock)    (read_unlock(lock), __sti())
  238. #define write_lock_irq(lock)    (__cli(), write_lock(lock))
  239. #define write_unlock_irq(lock)    (write_unlock(lock), __sti())
  240.  
  241. #define read_lock_irqsave(lock, flags)    \
  242.     (__save_and_cli(flags), read_lock(lock))
  243. #define read_unlock_irqrestore(lock, flags) \
  244.     (read_unlock(lock), __restore_flags(flags))
  245. #define write_lock_irqsave(lock, flags)    \
  246.     (__save_and_cli(flags), write_lock(lock))
  247. #define write_unlock_irqrestore(lock, flags) \
  248.     (write_unlock(lock), __restore_flags(flags))
  249.  
  250. #endif /* SMP */
  251. #endif /* _ALPHA_SPINLOCK_H */
  252.